package com.derbysoft.synxisadapter.commons.protocoltest;

import com.derbysoft.synxisadapter.commons.dto.synxis.OTACancelRQ;
import com.derbysoft.synxisadapter.commons.dto.synxis.OTAHotelAvailRQ;
import com.derbysoft.synxisadapter.commons.dto.synxis.OTAHotelResRQ;
import com.derbysoft.synxisadapter.commons.dto.synxis.OTAPingRQ;
import com.derbysoft.synxisadapter.commons.exception.NetErrorException;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.client.core.WebServiceMessageCallback;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.soap.SoapHeader;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.xml.transform.StringSource;

import javax.xml.bind.Marshaller;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by: jason
 * Date: 2012-06-19
 */
public abstract class AbstractWebServiceTest extends JaxbUtils {
    private static Map<Class, String> soapActionMap = new HashMap<Class, String>();
    private static final String URL = "http://integcert.synxis.com/interface/ChannelConnect.asmx";//integration
//    private static final String URL = "http://interface.synxis.com/ChannelConnect.asmx";//PRODUCTION
    private static final String USERNAME = "DERBYSMSICRT";
    private static final String PASSWORD = "T$ci@7SyB";

//    private static final String USERNAME = "ICRTHOTELBEDS";
//    private static final String PASSWORD = "1@rT4oT3l$d3B";

    private static final String HEADER_TEMPLATE = "<HTNGHeader xmlns=\"http://htng.org/1.1/Header/\"><From><Credential>" +
            "<userName>" + USERNAME + "</userName><password>" + PASSWORD + "</password></Credential></From></HTNGHeader>";

    static {
        soapActionMap.put(OTACancelRQ.class, "http://synxis.com/OTA2004AService/CancelReservations");
        soapActionMap.put(OTAHotelAvailRQ.class, "http://synxis.com/OTA2004AService/CheckAvailability");
        soapActionMap.put(OTAHotelResRQ.class, "http://synxis.com/OTA2004AService/CreateReservations");
        soapActionMap.put(OTAPingRQ.class, "http://synxis.com/OTA2004AService/Ping");
    }

    protected WebServiceTemplate webServiceTemplate;
    protected Jaxb2Marshaller marshaller;

    private void initWebServiceTemplate() {
        initMarshaller();
        webServiceTemplate = new WebServiceTemplate();
        webServiceTemplate.setMarshaller(marshaller);
        webServiceTemplate.setUnmarshaller(marshaller);
        webServiceTemplate.setDefaultUri(URL);
    }

    protected void initMarshaller() {
        marshaller = new Jaxb2Marshaller();
        marshaller.setContextPath("com.derbysoft.synxisadapter.commons.dto.synxis");
        HashMap<String, Object> properties = new HashMap<String, Object>();
        properties.put(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setMarshallerProperties(properties);
    }

    public Object invoke(final Object rq) {
        try {
            initWebServiceTemplate();

            return webServiceTemplate.marshalSendAndReceive(rq, new WebServiceMessageCallback() {
                @Override
                public void doWithMessage(WebServiceMessage webServiceMessage) throws IOException, TransformerException {
                    SoapMessage soapMessage = (SoapMessage) webServiceMessage;

                    SoapHeader soapHeader = soapMessage.getSoapHeader();

                    soapMessage.setSoapAction(soapActionMap.get(rq.getClass()));

                    Transformer transformer = TransformerFactory.newInstance().newTransformer();

                    transformer.transform(new StringSource(HEADER_TEMPLATE), soapHeader.getResult());
                }
            });
        } catch (Exception e) {
            throw new NetErrorException(e.getMessage());
        }
    }
}
